const TaskNotification = require("../models/TaskNotification");
const Task = require("../models/Task");
const GroupMember = require("../models/GroupMember");
const User = require("../models/User");

class NotificationService {
  // 创建任务分配通知
  static async createTaskAssignedNotification(taskId, assigneeId, assignedBy) {
    try {
      const task = await Task.findById(taskId).populate("group", "name").lean();
      const assignedByUser = await User.findById(assignedBy).lean();

      if (!task || !assignedByUser) return;

      await TaskNotification.create({
        user: assigneeId,
        task: taskId,
        type: "task_assigned",
        title: "新任务分配",
        message: `${assignedByUser.username} 将任务 "${task.title}" 分配给了你`,
        metadata: {
          assignedBy: assignedBy,
          groupName: task.group.name,
        },
      });
    } catch (error) {
      console.error("创建任务分配通知失败:", error);
    }
  }

  // 创建任务更新通知
  static async createTaskUpdatedNotification(taskId, updatedBy, changes) {
    try {
      const task = await Task.findById(taskId).populate("group", "name").lean();
      const updatedByUser = await User.findById(updatedBy).lean();

      if (!task || !updatedByUser) return;

      // 通知任务创建者和分配者（如果不是更新者本人）
      const notifyUsers = [task.creator];
      if (task.assignee && String(task.assignee) !== String(updatedBy)) {
        notifyUsers.push(task.assignee);
      }

      for (const userId of notifyUsers) {
        if (String(userId) !== String(updatedBy)) {
          await TaskNotification.create({
            user: userId,
            task: taskId,
            type: "task_updated",
            title: "任务已更新",
            message: `${updatedByUser.username} 更新了任务 "${task.title}"`,
            metadata: {
              updatedBy: updatedBy,
              changes: changes,
              groupName: task.group.name,
            },
          });
        }
      }
    } catch (error) {
      console.error("创建任务更新通知失败:", error);
    }
  }

  // 创建任务完成通知
  static async createTaskCompletedNotification(taskId, completedBy) {
    try {
      const task = await Task.findById(taskId).populate("group", "name").lean();
      const completedByUser = await User.findById(completedBy).lean();

      if (!task || !completedByUser) return;

      // 通知任务创建者（如果不是完成者本人）
      if (String(task.creator) !== String(completedBy)) {
        await TaskNotification.create({
          user: task.creator,
          task: taskId,
          type: "task_completed",
          title: "任务已完成",
          message: `${completedByUser.username} 完成了任务 "${task.title}"`,
          metadata: {
            completedBy: completedBy,
            groupName: task.group.name,
          },
        });
      }

      // 通知小组管理员
      const admins = await GroupMember.find({
        group: task.group._id,
        role: { $in: ["owner", "admin"] },
        status: "accepted",
      }).lean();

      for (const admin of admins) {
        if (
          String(admin.user) !== String(completedBy) &&
          String(admin.user) !== String(task.creator)
        ) {
          await TaskNotification.create({
            user: admin.user,
            task: taskId,
            type: "task_completed",
            title: "任务已完成",
            message: `${completedByUser.username} 完成了任务 "${task.title}"`,
            metadata: {
              completedBy: completedBy,
              groupName: task.group.name,
            },
          });
        }
      }
    } catch (error) {
      console.error("创建任务完成通知失败:", error);
    }
  }

  // 创建评论通知
  static async createCommentNotification(taskId, commentAuthorId) {
    try {
      const task = await Task.findById(taskId).populate("group", "name").lean();
      const commentAuthor = await User.findById(commentAuthorId).lean();

      if (!task || !commentAuthor) return;

      // 通知任务创建者和分配者（如果不是评论者本人）
      const notifyUsers = [task.creator];
      if (task.assignee && String(task.assignee) !== String(commentAuthorId)) {
        notifyUsers.push(task.assignee);
      }

      for (const userId of notifyUsers) {
        if (String(userId) !== String(commentAuthorId)) {
          await TaskNotification.create({
            user: userId,
            task: taskId,
            type: "comment_added",
            title: "新评论",
            message: `${commentAuthor.username} 在任务 "${task.title}" 中添加了评论`,
            metadata: {
              commentAuthor: commentAuthorId,
              groupName: task.group.name,
            },
          });
        }
      }
    } catch (error) {
      console.error("创建评论通知失败:", error);
    }
  }

  // 创建截止时间提醒通知
  static async createDueDateReminderNotification(
    taskId,
    reminderType = "due_soon"
  ) {
    try {
      const task = await Task.findById(taskId).populate("group", "name").lean();

      if (!task || !task.assignee) return;

      const type =
        reminderType === "overdue" ? "task_overdue" : "task_due_soon";
      const title = reminderType === "overdue" ? "任务已逾期" : "任务即将到期";
      const message =
        reminderType === "overdue"
          ? `任务 "${task.title}" 已逾期，请尽快处理`
          : `任务 "${task.title}" 即将到期，请注意时间`;

      await TaskNotification.create({
        user: task.assignee,
        task: taskId,
        type: type,
        title: title,
        message: message,
        metadata: {
          groupName: task.group.name,
          dueDate: task.dueDate,
        },
      });
    } catch (error) {
      console.error("创建截止时间提醒通知失败:", error);
    }
  }

  // 批量创建截止时间提醒
  static async createDueDateReminders() {
    try {
      const now = new Date();
      const tomorrow = new Date(now.getTime() + 24 * 60 * 60 * 1000);
      const threeDaysLater = new Date(now.getTime() + 3 * 24 * 60 * 60 * 1000);

      // 查找即将到期的任务（1-3天内）
      const upcomingTasks = await Task.find({
        dueDate: { $gte: tomorrow, $lte: threeDaysLater },
        status: { $nin: ["completed", "cancelled"] },
        assignee: { $ne: null },
      }).lean();

      for (const task of upcomingTasks) {
        await this.createDueDateReminderNotification(task._id, "due_soon");
      }

      // 查找已逾期的任务
      const overdueTasks = await Task.find({
        dueDate: { $lt: now },
        status: { $nin: ["completed", "cancelled"] },
        assignee: { $ne: null },
      }).lean();

      for (const task of overdueTasks) {
        await this.createDueDateReminderNotification(task._id, "overdue");
      }

      console.log(
        `创建了 ${upcomingTasks.length} 个即将到期提醒和 ${overdueTasks.length} 个逾期提醒`
      );
    } catch (error) {
      console.error("批量创建截止时间提醒失败:", error);
    }
  }

  // 获取用户通知
  static async getUserNotifications(
    userId,
    page = 1,
    limit = 20,
    unreadOnly = false
  ) {
    try {
      const filter = { user: userId };
      if (unreadOnly) {
        filter.isRead = false;
      }

      const skip = (page - 1) * limit;

      const notifications = await TaskNotification.find(filter)
        .populate("task", "title status")
        .sort({ createdAt: -1 })
        .skip(skip)
        .limit(limit)
        .lean();

      const total = await TaskNotification.countDocuments(filter);

      return {
        notifications,
        pagination: {
          page,
          limit,
          total,
          pages: Math.ceil(total / limit),
        },
      };
    } catch (error) {
      console.error("获取用户通知失败:", error);
      throw error;
    }
  }

  // 标记通知为已读
  static async markAsRead(notificationId, userId) {
    try {
      const notification = await TaskNotification.findOneAndUpdate(
        { _id: notificationId, user: userId, isRead: false },
        {
          $set: {
            isRead: true,
            readAt: new Date(),
          },
        },
        { new: true }
      );

      return notification;
    } catch (error) {
      console.error("标记通知为已读失败:", error);
      throw error;
    }
  }

  // 标记所有通知为已读
  static async markAllAsRead(userId) {
    try {
      const result = await TaskNotification.updateMany(
        { user: userId, isRead: false },
        {
          $set: {
            isRead: true,
            readAt: new Date(),
          },
        }
      );

      return result.modifiedCount;
    } catch (error) {
      console.error("标记所有通知为已读失败:", error);
      throw error;
    }
  }

  // 获取未读通知数量
  static async getUnreadCount(userId) {
    try {
      return await TaskNotification.countDocuments({
        user: userId,
        isRead: false,
      });
    } catch (error) {
      console.error("获取未读通知数量失败:", error);
      throw error;
    }
  }
}

module.exports = NotificationService;
